#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <signal.h>

typedef void (*sigfunc_rt)(int, siginfo_t*, void*);

sigfunc_rt signal_rt(int signo, sigfunc_rt func, sigset_t* mask) {
	struct sigaction act, oact;

	act.sa_sigaction = func;
	act.sa_mask = *mask;
	act.sa_flags |= SA_SIGINFO;
	if (signo == SIGALRM) {
		act.sa_flags |= SA_INTERRUPT;
	}
	else {
		act.sa_flags |= SA_RESTART;
	}

	if (sigaction(signo, &act, &oact) < 0)
		return (sigfunc_rt)(SIG_ERR);

	return oact.sa_sigaction;
}

void sig_rt(int signo, siginfo_t* info, void* context) {
	printf("received signal %d, code = %d, ival = %d\n", \
			signo, info->si_code, info->si_value.sival_int);
}

int main() {
	printf("%d - %d\n", SIGRTMAX, SIGRTMIN);
	
	int i, j;
	pid_t pid;
	sigset_t newset;
	union sigval val;

	if ((pid=fork()) == 0) {
		sigemptyset(&newset);
		sigaddset(&newset, SIGRTMAX);
		sigaddset(&newset, SIGRTMAX-1);
		sigaddset(&newset, SIGRTMAX-2);
		sigprocmask(SIG_BLOCK, &newset, NULL);
		
		signal_rt(SIGRTMAX, sig_rt, &newset);
		signal_rt(SIGRTMAX-1, sig_rt, &newset);
		signal_rt(SIGRTMAX-2, sig_rt, &newset);

		sleep(6);

		sigprocmask(SIG_UNBLOCK, &newset, NULL);
		sleep(3);
		exit(0);
	}

	sleep(3);
	for (i=SIGRTMAX; i>=SIGRTMAX-2; i--) {
		for (j=0; j<=2; j++) {
			val.sival_int = j;
			sigqueue(pid, i, val);
			printf("sent signal %d, val = %d\n", i, j);
		}
	}

	exit(0);
}
